/*
  ivl_sets.c  -  implementation functions from set theory

  This file is part of the IVL Library (LIBIVL).
  
  LIBIVL - library for interval computations 
  
  Copyright (c) 2007 Mateusz Paprocki

  The IVL Library is free software; you can redistribute it and/or modify
  it under the terms of the GNU Lesser General Public License as published
  by the Free Software Foundation; either version 2.1 of the License, or
  (at your option) any later version.

  The IVL Library is distributed in the hope that it will be useful, but
  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
  License for more details.

  You should have received a copy of the GNU Lesser General Public License
  along with the IVL Library; see the file LICENCE.  If not, write to
  the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
  Boston, MA 02110-1301, USA.
*/

#include "interval.h"

int ivl_union(ivl_ptr x, ivl_srcptr y) {
	int inexact = 0, inexact_left, inexact_right;
	
	if (DOM_UNDEFINED(x) || DOM_UNDEFINED(y))
		x->domain = IVL_UNDEFINED;
	else {
		if (mpfr_lessequal_p(IVL_LEFT(x), IVL_LEFT(y))) {
			if (mpfr_greaterequal_p(IVL_RIGHT(x), IVL_RIGHT(y)))
				x->domain |= y->domain;
			else {				
				if (mpfr_less_p(IVL_RIGHT(x), IVL_LEFT(y)))
					x->domain = IVL_PARTIAL;
				else
					x->domain |= y->domain;
				
				inexact_right = mpfr_set(IVL_RIGHT(x), IVL_RIGHT(y), GMP_RNDU);
			}
		} else {
			if (mpfr_less_p(IVL_RIGHT(x), IVL_RIGHT(y))) {				
				inexact_right = mpfr_set(IVL_RIGHT(x), IVL_RIGHT(y), GMP_RNDU);
				x->domain |= y->domain;
			} else {
				if (mpfr_greater_p(IVL_LEFT(x), IVL_RIGHT(y)))
					x->domain = IVL_PARTIAL;
				else
					x->domain |= y->domain;							
			}	
			
			inexact_left = mpfr_set(IVL_LEFT(x), IVL_LEFT(y), GMP_RNDD);
		}
		
		IVL_CHECK(x, x->domain, inexact, inexact_left, inexact_right);				
	}
		
	return inexact;
}

int ivl_intersect(ivl_ptr x, ivl_srcptr y) {
	int inexact = 0, inexact_left, inexact_right;
	
	if (DOM_UNDEFINED(x) || DOM_UNDEFINED(y))
		x->domain = IVL_UNDEFINED;
	else {
		if (mpfr_lessequal_p(IVL_LEFT(x), IVL_LEFT(y))) {
			if (mpfr_greaterequal_p(IVL_RIGHT(x), IVL_RIGHT(y)))
				inexact_right = mpfr_set(IVL_RIGHT(x), IVL_RIGHT(y), GMP_RNDU);
			else {				
				if (mpfr_less_p(IVL_RIGHT(x), IVL_LEFT(y))) {
					x->domain = IVL_UNDEFINED;
					return inexact;
				}				
			}
			
			inexact_left = mpfr_set(IVL_LEFT(x), IVL_LEFT(y), GMP_RNDD);
		} else {
			if (mpfr_greater_p(IVL_LEFT(x), IVL_RIGHT(y))) {
				x->domain = IVL_UNDEFINED;
				return inexact;
			} else
				if (mpfr_greater_p(IVL_RIGHT(x), IVL_RIGHT(y)))
					inexact_right = mpfr_set(IVL_RIGHT(x), IVL_RIGHT(y), GMP_RNDU);
		}
		
		IVL_CHECK(x, x->domain | y->domain, inexact, inexact_left, inexact_right);				
	}
	
	return inexact;
}

